package com.tct.ndocgen.controller;

import com.tct.ndocgen.FileUtil;
import com.tct.ndocgen.entity.Rs;
import com.tct.ndocgen.entity.enums.RsEnum;
import com.tct.ndocgen.util.RsUtil;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author Huhailong
 * @Description 文档自动生成接口类
 * @Date 2021/8/3.
 */
@RestController
@RequestMapping("/web")
public class RunController {

    @Value("${upload.save-path}")
    private String uploadSavePath;
    @Value("${my.server-host}")
    private String serverHost;
    @Value("${my.nginx}")
    private String nginx;
    @Value("${my.cdocgen}")
    private String cdocgen;
    @Value("${my.pandoc}")
    private String pandoc;

    /**
     * 新版生成方法
     * @param param 接收生成参数 {outFileName: 生成文档名称, keywordFile: key.ini关键字配置文件, keySaveDir: 临时保存key.ini文件夹, cFile: 保存c文件夹}
     * @return 返回生成结果
     * @throws IOException 异常处理
     */
    @PostMapping("/makeDoc2")
    public Rs makeDoc2(@RequestBody Map<String, String> param) throws IOException {
        String outFileName = param.get("docName");
        String keywordFile = param.get("iFile");
        String keySaveDir = param.get("saveDir");
        String cFIle = param.get("cFile");
        String keyType = param.get("keyType");
        Runtime runtime = Runtime.getRuntime();
        //创建唯一历史文件夹
        String tempUrl = UUID.randomUUID().toString().replace("-", "");
        File tempUrlFile = new File(nginx+tempUrl+"/");
        boolean mkdirs = tempUrlFile.mkdirs();
        if(!mkdirs){
            RsUtil.error(RsEnum.SYSTEM_ERROR,"生成文件夹失败");
        }
        //创建执行脚本命令
        String command = cdocgen+" --md --output="+nginx +tempUrl+"/"+ outFileName + ".md --keyword=" + keywordFile + " " + cFIle+"*.c";
        Process process = runtime.exec(command);    //执行脚本
        String run = run(process);
        //将生成的image文件夹拷贝到nginx的文件服务器路径下
        FileUtils.copyDirectory(new File("images"), new File(nginx+tempUrl));
        //替换生成的md文件中的图片地址为文件服务器地址
        String result = readMd2(nginx+tempUrl+"/" + outFileName + ".md",tempUrl);
        //封装返回结果
        Map<String, String> map = new HashMap<>();
        map.put("downloadUrl", serverHost + "/"+tempUrl+"/" + outFileName + ".md");
        map.put("savePath", nginx+tempUrl+"/" + outFileName + ".md");
        map.put("makeDownFile", result);
        map.put("uuid",tempUrl);
        map.put("log",run);
        //删除临时文件夹
        System.out.println(cFIle);
        File cDir = new File(cFIle);
        FileUtils.deleteDirectory(cDir);
        if("upload".equals(keyType)){
            File iDir = new File(keySaveDir);
            FileUtils.deleteDirectory(iDir);
        }
        return RsUtil.success("生成成功", map);
    }

    public String run(Process process) {
        StringBuilder returnStr = new StringBuilder();
        try {
            BufferedReader result = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
            BufferedReader errMessage = new BufferedReader(new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8));
            String resultLine;
            String errLine;
            returnStr.append("<code>");
            while ((resultLine = result.readLine()) != null) {
                returnStr.append(resultLine);
            }
            returnStr.append("</code>");
            result.close();
            while ((errLine = errMessage.readLine()) != null) {
                returnStr.append("<br>");
                returnStr.append("<span style='color: red;'>").append(errLine).append("</span>");
            }
            errMessage.close();
            process.waitFor();
        } catch (IOException | InterruptedException e) {
            e.getMessage();
        }
        return returnStr.toString();
    }


    private String readMd2(String filePath,String tempUrl) throws IOException {
        FileInputStream in = new FileInputStream(filePath);
        BufferedInputStream bis = new BufferedInputStream(in);
        byte[] buffer = new byte[1024];
        int bytesRead;
        StringBuilder result = new StringBuilder();
        while ((bytesRead = bis.read(buffer)) != -1) {
            String temp = new String(buffer, 0, bytesRead);
            String replaceTemp = temp.replace("images", serverHost+"/" +tempUrl);
            result.append(replaceTemp);
        }
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream((filePath)), StandardCharsets.UTF_8);
        writer.write(result.toString());
        writer.flush();
        writer.close();
        bis.close();
        return result.toString();
    }

    @PostMapping("/upload")
    public Rs uploadFile(List<MultipartFile> files) throws IOException {
        if (files == null) {
            return RsUtil.error(RsEnum.SYSTEM_ERROR, "上传文件为空");
        }
        String tempDir = UUID.randomUUID().toString().replace("-", "");
        String trueSavePath = uploadSavePath+tempDir+"/";
        File tempFile = new File(trueSavePath);
        boolean mkdirs = tempFile.mkdirs();
        if (!mkdirs) {
            RsUtil.error(RsEnum.SYSTEM_ERROR,"文件夹创建失败");
        }
        Map<String, Object> map = new HashMap<>();
        for (MultipartFile file : files) {

            String fileFullName = file.getOriginalFilename();
            assert fileFullName != null;
            String suffix = FileUtil.getSuffix(fileFullName);
            if ("c".equalsIgnoreCase(suffix) || "ini".equalsIgnoreCase(suffix)) {
                String nonSuffixFileName = FileUtil.getNonSuffixFileName(fileFullName);
                String uuid = UUID.randomUUID().toString();
                String replace = uuid.replace("-", "");
                String saveFileName = nonSuffixFileName + "-" + replace + "." + suffix;
                File file1 = new File(trueSavePath+ saveFileName);
                file.transferTo(file1);
                if ("c".equalsIgnoreCase(suffix)) {
                    map.put("type", "c");
                }
                if ("ini".equalsIgnoreCase(suffix)) {
                    map.put("type", "ini");
                    map.put("saveDir",trueSavePath);
                    trueSavePath = trueSavePath+saveFileName;
                }
            } else {
                return RsUtil.error(RsEnum.SYSTEM_ERROR, "上传的文件格式不符合要求");
            }
        }
        map.put("path", trueSavePath);
        map.put("uuid", tempDir);
        return RsUtil.success("上传成功", map);
    }

    @PostMapping("/saveMd")
    public Rs saveMd(@RequestBody Map<String, String> map) throws IOException {
        String path = map.get("path");
        String content = map.get("content");
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream((path)), StandardCharsets.UTF_8);
        writer.write(content);
        writer.flush();
        writer.close();
        return RsUtil.success("保存成功");
    }

    @GetMapping("/getDescribe")
    public Rs getDescribe(String type) throws IOException {
        String result;
        if ("online".equalsIgnoreCase(type)) {
            result = getContent(nginx+"online.md");
        } else if("offline".equalsIgnoreCase(type)) {
            result = getContent(nginx+"offline.md");
        } else {
            result = getContent(nginx+"help.md");
        }
        return RsUtil.success("获取成功", result);
    }

    public String getContent(String filePath) throws IOException {
        FileInputStream in = new FileInputStream(filePath);
        BufferedInputStream bis = new BufferedInputStream(in);
        byte[] buffer = new byte[1024];
        int bytesRead;
        StringBuilder result = new StringBuilder();
        while ((bytesRead = bis.read(buffer)) != -1) {
            String temp = new String(buffer, 0, bytesRead);
            result.append(temp);
        }
        in.close();
        bis.close();
        return result.toString();
    }

    @GetMapping("/getDocx")
    public Rs convertDocxByMd(String savePath, String fileName, String uuid) throws IOException {
        Runtime runtime = Runtime.getRuntime();
        String command = pandoc+" " + savePath + " -o " + FileUtil.getNonSuffixFileName(savePath) + ".docx --reference-doc="+nginx+"custom.docx";
        System.out.println(command);
        Process process = runtime.exec(command);
        run(process);
        return RsUtil.success("转换成功", serverHost + "/"+uuid+"/" + fileName + ".docx");
    }


}
